package com.huawang.mdesign.model.service.inter;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.huawang.business.command.CommandAddType;
import com.huawang.business.command.CommandParameter;
import com.huawang.business.constants.AllocationModeEnum;
import com.huawang.business.constants.ErrorCode;
import com.huawang.business.constants.ModelConstantURI;
import com.huawang.business.constants.PinType;
import com.huawang.business.dto.*;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.service.model.base.ElementNameService;
import com.huawang.business.service.model.base.UmlService;
import com.huawang.business.service.model.core.InternalUmlService;
import com.huawang.business.service.model.core.ModelPropertyInfoService;
import com.huawang.business.service.model.core.add.IModelOperation;
import com.huawang.business.service.model.core.delete.DeleteService;
import com.huawang.business.service.model.core.property.PropertyManager;
import com.huawang.business.service.model.core.property.UpdateModelFactory;
import com.huawang.business.service.model.core.property.update.UpdateActivityNodeInPartition;
import com.huawang.business.service.model.core.property.update.UpdateCustomizationCommandActionTimePoint;
import com.huawang.business.service.model.core.property.update.UpdateInPartitionByUsageMode;
import com.huawang.business.service.transaction.TransactionServiceImpl;
import com.huawang.business.util.InstanceVoUtils;
import com.huawang.business.vo.ModelResultVo;
import com.huawang.business.vo.PinTypeVo;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.cmof.reflection.impl.BasicRElement;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.semantics.constants.TypeEnum;
import com.huawang.core.semantics.entity.queryResult.MofResultContainer;
import com.huawang.core.semantics.entity.queryResult.QueryPropertyForm;
import com.huawang.core.semantics.entity.transaction.LocalTransaction;
import com.huawang.core.semantics.exception.LocalTransactionNotStartException;
import com.huawang.core.semantics.exception.TransactionNotExistingException;
import com.huawang.mdesign.model.service.constant.UAFDefinitionConstants;
import com.huawang.mdesign.model.service.dto.*;
import com.huawang.mdesign.model.service.util.LogUtil;
import com.huawang.mdesign.model.service.vo.selectelementitem.SelectElementItem;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.huawang.business.constants.ModelActionName.*;

@Slf4j
@Service
@Primary
public class ActivityService {

    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private UmlService umlService;

    @Autowired
    private ModelService modelService;

    @Autowired
    private PropertyManager propertyManager;

    @Autowired
    private UpdateActivityNodeInPartition updateActivityNodeInPartition;

    @Autowired
    private UpdateInPartitionByUsageMode updateInPartitionByUsageMode;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Autowired
    private ItemFlowService itemFlowService;

    @Autowired
    private UpdateCustomizationCommandActionTimePoint updateCustomizationCommandActionTimePoint;

    @Autowired
    private TransactionServiceImpl transactionService;

    @Autowired
    private ElementNameService elementNameService;

    @Autowired
    private DeleteService deleteService;

    private static final Map<String, PinType> PROPERTY_NAME2_PIN_TYPE_MAPPING = new HashMap<>();

    private static final String PROJECT_INSTANCE_LOG = "projectId：{}, instanceId：{}";

    static {
        // input
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.CallOperationAction_target, PinType.TARGET);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.StartObjectBehaviorAction_object, PinType.OBJECT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.StructuralFeatureAction_object, PinType.OBJECT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.SendSignalAction_target, PinType.TARGET);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.AddStructuralFeatureValueAction_insertAt, PinType.INSERT_AT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.WriteStructuralFeatureAction_value, PinType.VALUE);
        // output
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.CreateObjectAction_result, PinType.RESULT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.ReadSelfAction_result, PinType.RESULT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.ValueSpecificationAction_result, PinType.RESULT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.ReadStructuralFeatureAction_result, PinType.RESULT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.ClearStructuralFeatureAction_result, PinType.RESULT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.ReadExtentAction_result, PinType.RESULT);
        PROPERTY_NAME2_PIN_TYPE_MAPPING.put(UMLDefinitionConstants.WriteStructuralFeatureAction_result, PinType.RESULT);
    }

    @NotNull
    public List<PinTypeVo> queryInputPinTypes(final String projectId, final String instanceId) {
        LogUtil.printOnlineLogs(PROJECT_INSTANCE_LOG, projectId, instanceId);
        MetaClassInstance action = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(action)) {
            return Collections.emptyList();
        }
        Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, action);

        if (givenTypes.contains(UMLDefinitionConstants.CallBehaviorAction)) {
            return Collections.singletonList(PinType.ARGUMENT.getValue());
        } else if (givenTypes.contains(UMLDefinitionConstants.CallOperationAction)) {
            return this.createActionTypeList(projectId, action, UMLDefinitionConstants.CallOperationAction_target);
        } else if (givenTypes.contains(UMLDefinitionConstants.StartObjectBehaviorAction)) {
            return this.createActionTypeList(projectId, action, UMLDefinitionConstants.StartObjectBehaviorAction_object);
        } else if (givenTypes.contains(UMLDefinitionConstants.ReadSelfAction)
                || givenTypes.contains(UMLDefinitionConstants.ValueSpecificationAction)) {
            return Collections.emptyList();
        } else if (givenTypes.contains(UMLDefinitionConstants.ReadStructuralFeatureAction)
                || givenTypes.contains(UMLDefinitionConstants.ClearStructuralFeatureAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.StructuralFeatureAction_object);
        } else if (givenTypes.contains(UMLDefinitionConstants.OpaqueAction)) {
            return Collections.singletonList(PinType.INPUT_VALUE.getValue());
        } else if (givenTypes.contains(UMLDefinitionConstants.AddStructuralFeatureValueAction)) {
            return this.createAddStructuralFeatureValueActionTypeList(projectId, action);
        } else if (givenTypes.contains(UMLDefinitionConstants.SendSignalAction)) {
            return this.createActionTypeList(projectId, action, UMLDefinitionConstants.SendSignalAction_target);
        } else if (givenTypes.contains(UMLDefinitionConstants.LoopNode)) {
            return Collections.singletonList(PinType.LOOP_VARIABLE_INPUT.getValue());
        } else if (givenTypes.contains(UMLDefinitionConstants.StructuredActivityNode)) {
            return Collections.singletonList(PinType.STRUCTURED_NODE_INPUT.getValue());
        } else {
            return Collections.emptyList();
        }
    }

    @NotNull
    private List<PinTypeVo> createActionTypeList(@NotNull final String projectId,
                                                 @NotNull final MetaClassInstance action,
                                                 @NotNull final String pinKey) {
        LogUtil.printOnlineLogs("projectId: {}, action: {}, pinKey: {}", projectId, action.getId(), pinKey);
        final List<PinTypeVo> typeList = new ArrayList<>();
        typeList.add(PinType.ARGUMENT.getValue());
        typeList.addAll(getPinTypes(projectId, action, Collections.singletonList(pinKey)).stream()
                .map(PinType::getValue).collect(Collectors.toList()));
        return typeList;
    }

    @NotNull
    private List<PinTypeVo> createAddStructuralFeatureValueActionTypeList(@NotNull final String projectId,
                                                                          @NotNull final MetaClassInstance action) {
        LogUtil.printOnlineLogs("projectId: {}, action: {}", projectId, action.getId());
        return this.getPinTypes(projectId, action,
                Stream.of(UMLDefinitionConstants.StructuralFeatureAction_object,
                        UMLDefinitionConstants.AddStructuralFeatureValueAction_insertAt,
                        UMLDefinitionConstants.WriteStructuralFeatureAction_value).collect(Collectors.toList()))
                .stream()
                .map(PinType::getValue)
                .collect(Collectors.toList());
    }

    @NotNull
    public List<PinTypeVo> queryOutputPinTypes(final String projectId, final String instanceId) {
        LogUtil.printOnlineLogs("queryOutputPinTypes -> projectId: {}, instanceId: {}", projectId, instanceId);
        MetaClassInstance action = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(action)) {
            return Collections.emptyList();
        }

        Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, action);

        if (givenTypes.contains(UMLDefinitionConstants.CreateObjectAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.CreateObjectAction_result);
        } else if (givenTypes.contains(UMLDefinitionConstants.ReadSelfAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.ReadSelfAction_result);
        } else if (givenTypes.contains(UMLDefinitionConstants.ValueSpecificationAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.ValueSpecificationAction_result);
        } else if (givenTypes.contains(UMLDefinitionConstants.ReadStructuralFeatureAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.ReadStructuralFeatureAction_result);
        } else if (givenTypes.contains(UMLDefinitionConstants.ClearStructuralFeatureAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.ClearStructuralFeatureAction_result);
        } else if (givenTypes.contains(UMLDefinitionConstants.OpaqueAction)) {
            return Collections.singletonList(PinType.OUTPUT_VALUE.getValue());
        } else if (givenTypes.contains(UMLDefinitionConstants.ReadExtentAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.ReadExtentAction_result);
        } else if (givenTypes.contains(UMLDefinitionConstants.AddStructuralFeatureValueAction)) {
            return this.createPinTypeList(projectId, action, UMLDefinitionConstants.WriteStructuralFeatureAction_result);
        } else if (givenTypes.contains(UMLDefinitionConstants.SendSignalAction)) {
            return Collections.emptyList();
        } else if (givenTypes.contains(UMLDefinitionConstants.LoopNode)) {
            return Collections.singletonList(PinType.RESULT.getValue());
        } else if (givenTypes.contains(UMLDefinitionConstants.StructuredActivityNode)) {
            return Collections.singletonList(PinType.STRUCTURED_NODE_OUTPUT.getValue());
        } else {
            return Collections.singletonList(PinType.RESULT.getValue());
        }
    }

    @NotNull
    private List<PinTypeVo> createPinTypeList(@NotNull final String projectId,
                                              @NotNull final MetaClassInstance action,
                                              @NotNull final String propertyName) {
        LogUtil.printOnlineLogs("projectId: {}, action: {}, propertyName: {}", projectId, action.getId(), propertyName);
        return getPinTypes(projectId, action, Collections.singletonList(propertyName)).stream()
                .map(PinType::getValue).collect(Collectors.toList());
    }

    /**
     * 添加pin可创建类型
     *
     * @param projectId
     * @param action
     * @param propertyNames
     */
    @NotNull
    private List<PinType> getPinTypes(@NotNull final String projectId,
                                      @NotNull final MetaClassInstance action,
                                      @NotNull final List<String> propertyNames) {
        LogUtil.printOnlineLogs("projectId: {}, action: {}, propertyNames: {}", projectId, action.getId(), propertyNames);
        final List<PinType> result = new LinkedList<>();
        final String instanceId = action.getId();
        final QueryPropertyForm queryPropertyForm = this.internalUmlService.getQueryPropertyForm(action, propertyNames);
        final MofResultContainer mofResultContainer = this.internalUmlService.queryProperty(projectId, queryPropertyForm);
        for (String propertyName : propertyNames) {
            final MetaClassInstance metaClassInstance = mofResultContainer.queryInstanceProperty(instanceId, propertyName);
            if (Objects.isNull(metaClassInstance) && PROPERTY_NAME2_PIN_TYPE_MAPPING.containsKey(propertyName)) {
                result.add(PROPERTY_NAME2_PIN_TYPE_MAPPING.get(propertyName));
            }
        }
        return result;
    }

    @NotNull
    public ModelResultVo quickCreateActivityDiagram(final QuickCreateActivityDiagramDTO quickCreateActivityDiagramDto) {
        LogUtil.printSerializeOnlineLogs("quickCreateActivityDiagramDto: ", quickCreateActivityDiagramDto);
        ModelResultVo modelResultVo = new ModelResultVo();
        final String projectId = quickCreateActivityDiagramDto.getProjectId();
        final MetaClassInstance instance = internalUmlService.fetchExistInstance(quickCreateActivityDiagramDto.getInstanceId(), projectId);

        final ModelPropertyInfo model = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId, instance,
                Stream.of(UMLDefinitionConstants.Action_input, UMLDefinitionConstants.Action_output,
                        UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.ActivityNode_inPartition,
                        UMLDefinitionConstants.Action_context, UMLDefinitionConstants.CallBehaviorAction_behavior).collect(Collectors.toList()));

        final MetaClassInstance behavior = model.queryInstanceValue(UMLDefinitionConstants.CallBehaviorAction_behavior);
        final List<MetaClassInstance> inputs = model.queryListInstanceValue(UMLDefinitionConstants.Action_input);
        final List<MetaClassInstance> outputs = model.queryListInstanceValue(UMLDefinitionConstants.Action_output);

        MetaClassInstance activityDiagram;

        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            final String callBehaviorActionName = model.queryStringValue(UMLDefinitionConstants.NamedElement_name);
            List<String> activityDiagramAppliedStereotype = new ArrayList<>(1);
            List<String> activityAppliedStereotype = null;
            activityDiagramAppliedStereotype.add(UMLDefinitionConstants.SysMLActivityDiagram);
            // 如果传入的参数有构造型，则需要根据构造型获得对应的活动构造型
            if(quickCreateActivityDiagramDto.getApplyStereotypes() != null && !quickCreateActivityDiagramDto.getApplyStereotypes().isEmpty()) {
                activityDiagramAppliedStereotype = quickCreateActivityDiagramDto.getApplyStereotypes();
                activityAppliedStereotype = getActivityStereotypeByActivityDiagram(activityDiagramAppliedStereotype);
            }
            if (Objects.nonNull(behavior)) {
                final String behaviorName = internalUmlService.queryStringProperty(projectId, behavior,
                        UMLDefinitionConstants.NamedElement_name);
                if (internalUmlService.checkInstanceType(projectId, behavior, UMLDefinitionConstants.Activity)) {
                    final CommandParameter diagramParameter = CommandParameter.builder()
                            .projectId(projectId)
                            .parentId(behavior.getId())
                            .type(CommandAddType.MODEL)
                            .typeId(UMLDefinitionConstants.UMLDiagram)
                            .instanceId(ModelConstantURI.initInstanceId())
                            .applyStereotypes(activityDiagramAppliedStereotype)
                            .defaultName(behaviorName)
                            .build();
                    activityDiagram = umlService.addModel(diagramParameter);
                    String name = elementNameService.fetchDefaultName(projectId, behaviorName, behavior, activityDiagram);
                    umlService.updateModel(projectId, activityDiagram.getId(),
                            UMLDefinitionConstants.NamedElement_name, name);
                } else {
                    final MetaClassInstance activity = createActivity(projectId, behavior.getUUID(), activityAppliedStereotype,
                            callBehaviorActionName, behaviorName);
                    String name = elementNameService.fetchDefaultName(projectId,
                            StringUtils.isNotEmpty(callBehaviorActionName) ? callBehaviorActionName : behaviorName,
                            behavior, activity);
                    umlService.updateModel(projectId, activity.getId(), UMLDefinitionConstants.NamedElement_name, name);
                    umlService.updateModel(projectId, instance.getId(),
                            UMLDefinitionConstants.CallBehaviorAction_behavior, activity);

                    List<MetaClassInstance> inPartitions = model.queryListInstanceValue(
                            UMLDefinitionConstants.ActivityNode_inPartition);
                    updateActivityNodeInPartition.setInPartitionsByBatch(projectId, Stream.of(instance).collect(Collectors.toList()), inPartitions, quickCreateActivityDiagramDto.getAllocationMode());

                    final CommandParameter diagramParameter = CommandParameter.builder()
                            .projectId(projectId)
                            .parentId(activity.getId())
                            .type(CommandAddType.MODEL)
                            .typeId(UMLDefinitionConstants.UMLDiagram)
                            .instanceId(ModelConstantURI.initInstanceId())
                            .applyStereotypes(activityDiagramAppliedStereotype)
                            .defaultName(name)
                            .build();
                    activityDiagram = umlService.addModel(diagramParameter);
                    createParameterAndActivityParameterNodeV2(projectId, inputs, true, activity);
                    createParameterAndActivityParameterNodeV2(projectId, outputs, false, activity);
                }
            } else {
                // 状态机图中转换的effect属性为活动后，其活动图中的action快速创建活动图，父节点不应该是转换，应该是状态机
                String parentId = quickCreateActivityDiagramDto.getParentId();
                MetaClassInstance parent = internalUmlService.fetchInstance(parentId, projectId);
                if (internalUmlService.checkInstanceType(projectId, parent, UMLDefinitionConstants.Transition)) {
                    MetaClassInstance region = internalUmlService.queryInstanceProperty(projectId, parent, UMLDefinitionConstants.Element_owner);
                    MetaClassInstance stateMachine = internalUmlService.queryInstanceProperty(projectId, region, UMLDefinitionConstants.Element_owner);
                    if (Objects.nonNull(stateMachine)) {
                        parentId = stateMachine.getId();
                    }
                }
                AddModelDTO addModelDTO = new AddModelDTO();
                addModelDTO.setProjectId(projectId);
                addModelDTO.setParentId(parentId);
                addModelDTO.setMetaclass(UMLDefinitionConstants.UMLDiagram);
                addModelDTO.setType(CommandAddType.MODEL.getCode());
                addModelDTO.setApplyStereotypes(activityDiagramAppliedStereotype);

                final IModelOperation modelOperation = umlService.fetchModelOperation(UMLDefinitionConstants.UMLDiagram, null);
                activityDiagram = modelService.addModel(addModelDTO, modelOperation);
                MetaClassInstance activity = internalUmlService.queryInstanceProperty(
                        projectId, activityDiagram, UMLDefinitionConstants.Diagram_context);
                if (StrUtil.isNotBlank(callBehaviorActionName)) {
                    ModifyPropertyDTO modifyPropertyDTO = new ModifyPropertyDTO();
                    modifyPropertyDTO.setInstanceId(activity.getId());
                    modifyPropertyDTO.setProjectId(projectId);
                    modifyPropertyDTO.setKey(UMLDefinitionConstants.NamedElement_name);
                    modifyPropertyDTO.setValue(Collections.singletonList(callBehaviorActionName));
                    modifyPropertyDTO.setIsMultiplicity(false);
                    modifyPropertyDTO.setDataType(TypeEnum.STRING.getName());
                    propertyManager.updatePropertyValue(modifyPropertyDTO);
                }
                umlService.updateModel(projectId, instance.getId(), UMLDefinitionConstants.CallBehaviorAction_behavior, activity);

                List<MetaClassInstance> inPartitions = model.queryListInstanceValue(
                        UMLDefinitionConstants.ActivityNode_inPartition);
                updateActivityNodeInPartition.setInPartitionsByBatch(projectId, Stream.of(instance).collect(Collectors.toList()), inPartitions, quickCreateActivityDiagramDto.getAllocationMode());


                createParameterAndActivityParameterNodeV2(projectId, inputs, true, activity);
                createParameterAndActivityParameterNodeV2(projectId, outputs, false, activity);
            }


            transactionService.commit(projectId);
            modelResultVo.setInstanceId(activityDiagram.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.ADD_MODEL_ERROR, e);
        }

        return modelResultVo;
    }

    /**
     * 创建活动模型
     *
     * @param projectId
     * @param parentId
     * @param activityAppliedStereotype
     * @param callBehaviorActionName
     * @param contextName
     * @return
     */
    @NotNull
    private MetaClassInstance createActivity(String projectId, String parentId,
                                            List<String> activityAppliedStereotype, String callBehaviorActionName,
                                            String contextName) {
        final CommandParameter activityParameter = CommandParameter.builder()
                .projectId(projectId)
                .parentId(parentId)
                .typeId(UMLDefinitionConstants.Activity)
                .type(CommandAddType.MODEL)
                .instanceId(ModelConstantURI.initInstanceId())
                .defaultName(StringUtils.isNotEmpty(callBehaviorActionName) ? callBehaviorActionName : contextName)
                .build();
        if(activityAppliedStereotype != null && !activityAppliedStereotype.isEmpty()) {
            activityParameter.setApplyStereotypes(activityAppliedStereotype);
        }
        return umlService.addModel(activityParameter);
    }

    /**
     * 获得活动图对应的活动的构造型
     */
    private @NotNull List<String> getActivityStereotypeByActivityDiagram(List<String> activityDiagramStereotypes) {
        String activityDiagramStereotype = activityDiagramStereotypes.get(0);
        if(UAFDefinitionConstants.UAF_DIAGRAM_OV5_OPERATIONALACTIVITYMODEL.equals(activityDiagramStereotype) ||
                UAFDefinitionConstants.UAF_DIAGRAM_OPPR_OPERATIONALPROCESSFLOW.equals(activityDiagramStereotype)) {
            return Collections.singletonList(UMLDefinitionConstants.UAF_OperationalActivity);
        } else if(UAFDefinitionConstants.UAF_DIAGRAM_SV4_SYSTEMSFUNCTIONALITYFLOWDESCRIPTION.equals(activityDiagramStereotype) ||
                UAFDefinitionConstants.UAF_DIAGRAM_RSPR_RESOURCESPROCESSFLOW.equals(activityDiagramStereotype) ||
                UAFDefinitionConstants.UAF_DIAGRAM_PSPR_PERSONALPROCESSFLOW.equals(activityDiagramStereotype)) {
            return Collections.singletonList(UMLDefinitionConstants.UAF_Function);
        } else if(UAFDefinitionConstants.UAF_DIAGRAM_SVCV4_SERVICESFUNCTIONALITYFLOWDESCRIPTION.equals(activityDiagramStereotype) ||
                UAFDefinitionConstants.UAF_DIAGRAM_SVPR_SERVICESPROCESSFLOW.equals(activityDiagramStereotype)) {
            return Collections.singletonList(UMLDefinitionConstants.UAF_ServiceFunction);
        } else if(UAFDefinitionConstants.UAF_DIAGRAM_PJPR_PROJECTSPROCESSFLOW.equals(activityDiagramStereotype)) {
            return Collections.singletonList(UMLDefinitionConstants.UAF_ProjectActivity);
        } else if(UAFDefinitionConstants.UAF_DIAGRAM_SCPR_SECURITYPROCESS.equals(activityDiagramStereotype)) {
            return Collections.singletonList(UMLDefinitionConstants.UAF_SecurityProcess);
        } else {
            return Collections.emptyList();
        }
    }

    private void createParameterAndActivityParameterNodeV2(String projectId,
                                                           List<MetaClassInstance> pins,
                                                           Boolean isInputPin,
                                                           MetaClassInstance parent) {
        LogUtil.printOnlineLogs("projectId: {}, parent: {}", projectId, parent);
        if (CollectionUtils.isEmpty(pins)) {
            log.info("不存在输入或输出栓");
            return;
        }
        String enumerationLiteralName = BooleanUtils.isTrue(isInputPin) ?
                UMLDefinitionConstants.ParameterDirectionKind_in : UMLDefinitionConstants.ParameterDirectionKind_out;
        List<ModelPropertyInfo> pinInfos = modelPropertyInfoService.createModelPropertyInfoList(
                projectId,
                pins,
                Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.TypedElement_type)
                        .collect(Collectors.toList()));
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
        List<CommandParameter> commandParameters = new ArrayList<>();
        Map<String, String> activityParameterNodeWithParameterMap = new HashMap<>();
        Map<String, String> pinWithParameterMap = new HashMap<>();
        pinInfos.forEach(model -> {
            String activityParameterNodeId = ModelConstantURI.initInstanceId();
            final CommandParameter activityParameterNodeParameter = CommandParameter.builder()
                    .projectId(projectId)
                    .parentId(parent.getId())
                    .typeId(UMLDefinitionConstants.ActivityParameterNode)
                    .type(CommandAddType.MODEL)
                    .instanceId(activityParameterNodeId)
                    .defaultName(model.queryStringValue(UMLDefinitionConstants.NamedElement_name))
                    .build();
            commandParameters.add(activityParameterNodeParameter);
            final String parameterId = ModelConstantURI.initInstanceId();
            final CommandParameter parameterParameter = CommandParameter.builder()
                    .projectId(projectId)
                    .parentId(parent.getId())
                    .typeId(UMLDefinitionConstants.Parameter)
                    .type(CommandAddType.MODEL)
                    .instanceId(parameterId)
                    .defaultName(model.queryStringValue(UMLDefinitionConstants.NamedElement_name))
                    .build();
            commandParameters.add(parameterParameter);
            MetaClassInstance kind = internalUmlService.getEnumerationLiteral(projectId, enumerationLiteralName);
            updateModelDTOS.add(new UpdateModelDTO(projectId, parameterId, UMLDefinitionConstants.Parameter_direction, kind));
            activityParameterNodeWithParameterMap.put(activityParameterNodeId, parameterId);
            pinWithParameterMap.put(model.getInstanceId(), parameterId);
            // 活动参数节点类型与栓类型保持一致
            MetaClassInstance pinType = model.queryInstanceValue(UMLDefinitionConstants.TypedElement_type);
            updateModelDTOS.add(new UpdateModelDTO(projectId, activityParameterNodeId, UMLDefinitionConstants.TypedElement_type, pinType));
        });
        final List<MetaClassInstance> instanceList = umlService.addModelByBatch(commandParameters);
        final Map<String, MetaClassInstance> instanceMap = instanceList.stream().collect(Collectors.toMap(BasicRElement::getId, b -> b, (k, v) -> k));

        activityParameterNodeWithParameterMap.forEach((k, v) ->
                updateModelDTOS.add(new UpdateModelDTO(projectId, k, UMLDefinitionConstants.ActivityParameterNode_parameter, instanceMap.get(v)))
        );
        pinWithParameterMap.forEach((k, v) ->
                updateModelDTOS.add(new UpdateModelDTO(projectId, k, UMLDefinitionConstants.Element_syncElement, instanceMap.get(v)))
        );

        if (CollectionUtils.isNotEmpty(updateModelDTOS)) {
            umlService.updateModelByBatch(updateModelDTOS);
        }
    }


    /**
     * 查询活动下拥有的活动参数节点
     *
     * @param projectId
     * @param instanceId
     * @param activityParameterNodeIds 显示的活动参数节点模块，。。。
     * @return java.util.List<com.huawang.mdesign.model.service.vo.selectelementitem.SelectElementItem>
     * @author baibf
     * @date 2022/08/25 14:55
     */
    @NotNull
    public List<SelectElementItem> queryActivityParameterNodes(String projectId, String instanceId,
                                                               List<String> activityParameterNodeIds) {
        LogUtil.printOnlineLogs("projectId: {}, instanceId: {}, activityParameterNodeIds: {}", projectId, instanceId, activityParameterNodeIds);
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            return Collections.emptyList();
        }

        MetaClassInstance activity = internalUmlService.queryInstanceProperty(projectId, instance,
                UMLDefinitionConstants.Element_owner);
        List<MetaClassInstance> nodes = internalUmlService.queryListInstanceProperty(projectId,
                activity, UMLDefinitionConstants.Activity_node);
        Map<String, Set<String>> givenTypes = internalUmlService.getGivenTypes(projectId, nodes);
        List<MetaClassInstance> activityParameterNodes = nodes.stream()
                .filter(it -> givenTypes.get(it.getId()).contains(UMLDefinitionConstants.ActivityParameterNode))
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(activityParameterNodeIds)) {
            // 移除已经显示的元素
            final Set<String> activityParameterNodeIdSet = new HashSet<>(activityParameterNodeIds);
            activityParameterNodes.removeIf(it -> activityParameterNodeIdSet.contains(it.getId()));
        }

        List<ModelPropertyInfo> activityParameterNodeModels = CollectionUtils.isNotEmpty(activityParameterNodes) ?
                modelPropertyInfoService.createModelPropertyInfoList(
                        projectId, activityParameterNodes,
                        Stream.of(UMLDefinitionConstants.NamedElement_name).collect(Collectors.toList())) :
                new ArrayList<>(0);

        final Map<String, String> iconMap = this.modelPropertyInfoService.queryIconBatch(projectId, activityParameterNodes);

        return activityParameterNodeModels.stream().map(model -> {
            SelectElementItem selectElementItem = new SelectElementItem();
            selectElementItem.setInstanceId(model.getInstance().getId());
            selectElementItem.setName(model.queryStringValue(UMLDefinitionConstants.NamedElement_name));
            selectElementItem.setIcon(iconMap.get(model.getInstanceId()));
            return selectElementItem;
        }).collect(Collectors.toList());
    }

    @NotNull
    public String queryParameterCorrespondingNode(final String projectId, final String instanceId) {
        LogUtil.printOnlineLogs("queryOutputPinTypes -> projectId: {}, instanceId: {}", projectId, instanceId);
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            return "";
        }
        final QueryPropertyForm queryPropertyForm = this.internalUmlService.getQueryPropertyForm(
                instance, UMLDefinitionConstants.A_parameter_activityParameterNode_activityParameterNode);
        final MofResultContainer mofResultContainer = this.internalUmlService.queryProperty(projectId, queryPropertyForm);
        return mofResultContainer.queryListInstanceProperty(instanceId, UMLDefinitionConstants.A_parameter_activityParameterNode_activityParameterNode)
                .stream().map(BasicRElement::getId).findFirst().orElse("");
    }

    @NotNull
    public ModelResultVo createActionWithActivity(CreateActionWithActivityDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto: ", dto);
        ModelResultVo modelResultVo = new ModelResultVo();
        final String projectId = dto.getProjectId();
        final Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(
                Stream.of(dto.getDiagramId(), dto.getActionId()).collect(Collectors.toList()), projectId);

        final MetaClassInstance diagramInstance = instanceMap.getOrDefault(dto.getDiagramId(), null);
        final MetaClassInstance actionInstance = instanceMap.getOrDefault(dto.getActionId(), null);
        if (Objects.isNull(diagramInstance) || Objects.isNull(actionInstance)) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        //确定Activity要放置的位置
        final Map<String, ModelPropertyInfo> infoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId,
                Stream.of(diagramInstance, actionInstance).collect(Collectors.toList()),
                Stream.of(UMLDefinitionConstants.Element_owner,
                        UMLDefinitionConstants.ActivityNode_inPartition).collect(Collectors.toList()));
        final ModelPropertyInfo diagramInfo = infoMap.getOrDefault(dto.getDiagramId(), null);
        final ModelPropertyInfo actionInfo = infoMap.getOrDefault(dto.getActionId(), null);
        if (Objects.isNull(diagramInfo) || Objects.isNull(actionInfo)) {
            throw AbortExecutionException.build(ErrorCode.PROPERTY_QUERY_ERROR);
        }
        final MetaClassInstance ownerInstance = diagramInfo.queryInstanceValue(UMLDefinitionConstants.Element_owner);
        final MetaClassInstance targetInstance = internalUmlService.queryInstanceProperty(projectId, ownerInstance,
                UMLDefinitionConstants.Element_owner);
        if (targetInstance == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }


        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            CreateModelDto createModelDto = new CreateModelDto(projectId);
            final String activityId = ModelConstantURI.initInstanceId();
            final CommandParameter activityParameter = CommandParameter.builder()
                    .type(CommandAddType.MODEL)
                    .typeId(UMLDefinitionConstants.Activity)
                    .projectId(projectId)
                    .instanceId(activityId)
                    .parentId(targetInstance.getId())
                    .build();
            createModelDto.addParameter(activityParameter);
            MetaClassInstance activityInstance = umlService.addModel(activityParameter);
            umlService.updateModel(projectId, dto.getActionId(), UMLDefinitionConstants.CallBehaviorAction_behavior, activityInstance);

            final List<MetaClassInstance> inPartitions = actionInfo.queryListInstanceValue(UMLDefinitionConstants.ActivityNode_inPartition);
            updateActivityNodeInPartition.removeInPartitionsByBatch(projectId, Stream.of(actionInstance).collect(Collectors.toList()),
                    inPartitions, Collections.emptyList(), dto.getAllocationMode());
            updateActivityNodeInPartition.setInPartitionsByBatch(projectId, Stream.of(actionInstance).collect(Collectors.toList()),
                    inPartitions, dto.getAllocationMode());

            transactionService.commit(projectId);
            modelResultVo.setInstanceId(activityInstance.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.ADD_MODEL_ERROR, e);
        }

        return modelResultVo;
    }

    @NotNull
    public ModelResultVo createEntityByDrag(CreateEntityByDragDTO createEntityByDragDTO) {
        LogUtil.printSerializeOnlineLogs("createEntityByDragDTO: ", createEntityByDragDTO);
        // 1.插入模型:根据插入method更改插入模型间关系 2.特殊情况:插入模型上存在项流，进行相应处理
        ModelResultVo modelResultVo = new ModelResultVo();
        final String projectId = createEntityByDragDTO.getProjectId();
        MetaClassInstance dragModel = internalUmlService.fetchInstance(createEntityByDragDTO.getSourceModelId(), projectId);
        MetaClassInstance plugModel = internalUmlService.fetchInstance(createEntityByDragDTO.getTargetModelId(), projectId);
        MetaClassInstance relationshipModel = internalUmlService.fetchInstance(createEntityByDragDTO.getRelationshipId(), projectId);
        if (Objects.isNull(relationshipModel)) {
            log.error("新增关系模型不存在");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        if (Objects.isNull(dragModel) || Objects.isNull(plugModel)) {
            log.error("拖拽模型或待插入模型不存在");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        // 通过被插入关系模型判断为状态图或活动图
        final Set<String> givenTypes = internalUmlService.getGivenTypes(projectId, plugModel);
        MetaClassInstance plugModelSource;
        MetaClassInstance plugModelTarget;
        String relationShipSource;
        String relationShipTarget;
        if (givenTypes.contains(UMLDefinitionConstants.ActivityEdge)) {
            plugModelSource = internalUmlService.queryInstanceProperty(projectId, plugModel, UMLDefinitionConstants.ActivityEdge_source);
            plugModelTarget = internalUmlService.queryInstanceProperty(projectId, plugModel, UMLDefinitionConstants.ActivityEdge_target);
            relationShipSource = UMLDefinitionConstants.ActivityEdge_source;
            relationShipTarget = UMLDefinitionConstants.ActivityEdge_target;
        } else if (givenTypes.contains(UMLDefinitionConstants.Transition)) {
            plugModelSource = internalUmlService.queryInstanceProperty(projectId, plugModel, UMLDefinitionConstants.Transition_source);
            plugModelTarget = internalUmlService.queryInstanceProperty(projectId, plugModel, UMLDefinitionConstants.Transition_target);
            relationShipSource = UMLDefinitionConstants.Transition_source;
            relationShipTarget = UMLDefinitionConstants.Transition_target;
        } else {
            log.error("被插入模型类型错误， 即不是活动边也不是转换");
            throw AbortExecutionException.build(ErrorCode.INSTANCE_TYPE_ERROR);
        }
        if (Objects.isNull(plugModelSource) || Objects.isNull(plugModelTarget)) {
            log.error("待插入模型两端不存在");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        LocalTransaction transaction = transactionService.createTransaction(projectId, UPDATE_MODEL);
        try {
            // 项流特殊处理
            List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
            if (internalUmlService.checkInstanceType(projectId, plugModel, UMLDefinitionConstants.ActivityEdge)) {
                changeRelatedItemFlow(projectId, plugModel, dragModel, relationshipModel);
            }
            if (Objects.equals(createEntityByDragDTO.getMethod(), "insertBefore")) {
                // 插入在转换前: 直接将待插入关系模型的目标设置为拖拽元素
                updateModelDTOS.add(UpdateModelFactory.newInstance(projectId, plugModel.getId(), relationShipSource, dragModel));
            } else if (Objects.equals(createEntityByDragDTO.getMethod(), "insertAfter")) {
                // 插入在转换后: 直接将待插入关系模型的源设置为拖拽元素
                updateModelDTOS.add(UpdateModelFactory.newInstance(projectId, plugModel.getId(), relationShipTarget, dragModel));
            } else {
                log.info("插入方式为:{}, 此时不做特殊处理", createEntityByDragDTO.getMethod());
            }
            if (CollectionUtils.isNotEmpty(updateModelDTOS)) {
                umlService.updateModelByBatch(updateModelDTOS);
            }
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(dragModel.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.UPDATE_MODEL_ERROR, e);
        }

        return modelResultVo;
    }

    /**
     * desciption:变更插入后连线的相关项流实现边属性
     */
    private void changeRelatedItemFlow(String projectId,
                                       MetaClassInstance plugModel,
                                       MetaClassInstance dragModel,
                                       MetaClassInstance relationshipModel) {
        LogUtil.printOnlineLogs("projectId: {}, plugModel: {}, dragModel: {}, relationshipModel: {}", projectId,
                plugModel.getId(), dragModel.getId(), relationshipModel.getId());
        // 获取插入关系模型上的项流
        List<MetaClassInstance> informationFlowList = internalUmlService.queryListInstanceProperty(
                projectId, plugModel, UMLDefinitionConstants.A_realizingActivityEdge_informationFlow_informationFlow);
        if (CollectionUtils.isEmpty(informationFlowList)) {
            log.info("活动边上不存在项流");
            return;
        }
        MofResultContainer informationFlowContainer = internalUmlService.queryProperty(projectId, internalUmlService.getQueryPropertyForm(
                informationFlowList,
                Stream.of(UMLDefinitionConstants.InformationFlow_informationSource,
                        UMLDefinitionConstants.InformationFlow_informationTarget).collect(Collectors.toList())));
        informationFlowList.forEach(it -> {
            // 如果活动图中加入特殊节点， 则需要添加项流的实现边
            if (internalUmlService.checkInstanceType(projectId, dragModel, UMLDefinitionConstants.ControlNode)) {
                umlService.appendModel(projectId, it.getId(), UMLDefinitionConstants.InformationFlow_realizingActivityEdge, relationshipModel);
            } else {
                MetaClassInstance source = informationFlowContainer.queryListInstanceProperty(
                        it.getId(), UMLDefinitionConstants.InformationFlow_informationSource).get(0);
                MetaClassInstance target = informationFlowContainer.queryListInstanceProperty(
                        it.getId(), UMLDefinitionConstants.InformationFlow_informationTarget).get(0);
                List<String> edgeList = itemFlowService.findAllRealizing(projectId, plugModel.getId(), source.getId(), target.getId());
                // 移除项流上活动路径上的所有实现边
                List<MetaClassInstance> edgeInstanceList = CollectionUtils.isEmpty(edgeList) ?
                        new ArrayList<>() : internalUmlService.fetchInstanceByIds(edgeList, projectId);
                // findAllRealizingByActivity方法查找出的活动路径不包含当前边
                edgeInstanceList.add(plugModel);
                // plugModel校验过不为空，所以edgeInstanceList也一定不为空
                edgeInstanceList.forEach(edgeInstance ->
                        umlService.removeModel(projectId, it.getId(), UMLDefinitionConstants.InformationFlow_realizingActivityEdge, edgeInstance));
            }
        });
    }

    @NotNull
    public ModelResultVo createCommandAction(CreateCommandActionDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto:", dto);
        final String projectId = dto.getProjectId();
        final String timeLineId = dto.getTimeLineId();

        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        ModelResultVo modelResultVo = new ModelResultVo();
        try {
            CommandParameter parameter = CommandParameter.builder()
                    .type(CommandAddType.initCommitStatus(0))
                    .typeId(UMLDefinitionConstants.Action)
                    .projectId(projectId)
                    .instanceId(ModelConstantURI.initInstanceId())
                    .parentId(dto.getParentId())
                    .applyStereotypes(Collections.singletonList(UMLDefinitionConstants.Customization_CommandAction))
                    .build();
            MetaClassInstance commandActionInstance = umlService.addModel(parameter);
            MetaClassInstance timeLineInstance = internalUmlService.fetchInstance(timeLineId, projectId);
            if (Objects.isNull(timeLineInstance)) {
                log.error("时间线模型模型查找失败");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            // 更新时间线的ownedCommandAction属性
            umlService.appendModel(projectId,
                    timeLineId,
                    UMLDefinitionConstants.Customization_TimeLine_OwnedCommandAction,
                    commandActionInstance);
            // 更新指令动作的TimeLineDependency属性
            umlService.updateModel(projectId,
                    commandActionInstance.getId(),
                    UMLDefinitionConstants.Customization_CommandAction_TimelineDependency,
                    timeLineInstance);

            // 更新动作指令的timePoint属性
            ModifyPropertyDTO modifyPropertyDTO = new ModifyPropertyDTO();
            modifyPropertyDTO.setProjectId(projectId);
            modifyPropertyDTO.setInstanceId(commandActionInstance.getId());
            modifyPropertyDTO.setKey(UMLDefinitionConstants.Customization_CommandAction_TimePoint);
            modifyPropertyDTO.setValue(dto.getValue());
            modifyPropertyDTO.setDataType(TypeEnum.REAL.getName());
            modifyPropertyDTO.setIsMultiplicity(false);
            updateCustomizationCommandActionTimePoint.updateValue(modifyPropertyDTO);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(commandActionInstance.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.ADD_MODEL_ERROR, e);
        }
        return modelResultVo;
    }

    @NotNull
    public List<String> queryRepresentsOfSwimLines(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("queryRepresentsOfSwimLines -> projectId: {}, instanceId: {}", projectId, instanceId);
        final MetaClassInstance diagramInstance = internalUmlService.fetchExistInstance(instanceId, projectId);
        final MetaClassInstance owner = internalUmlService.queryInstanceProperty(projectId, diagramInstance,
                UMLDefinitionConstants.Element_owner);
        if (Objects.isNull(owner)) {
            log.error("活动图父节点不存在");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        final Map<String, ModelPropertyInfo> infoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId,
                Stream.of(diagramInstance, owner).collect(Collectors.toList()),
                Stream.of(UMLDefinitionConstants.Behavior_context, UMLDefinitionConstants.Diagram_context).collect(Collectors.toList()));
        MetaClassInstance contextInstance = infoMap.containsKey(owner.getId()) ?
                infoMap.get(owner.getId()).queryInstanceValue(UMLDefinitionConstants.Behavior_context) : null;
        if (Objects.isNull(contextInstance)) {
            contextInstance = infoMap.containsKey(diagramInstance.getId()) ?
                    infoMap.get(diagramInstance.getId()).queryInstanceValue(UMLDefinitionConstants.Diagram_context) : null;
        }
        if (Objects.isNull(contextInstance)
                || !internalUmlService.checkInstanceType(projectId, contextInstance, UMLDefinitionConstants.Class)) {
            return Collections.emptyList();
        }
        final List<MetaClassInstance> classInstanceList = internalUmlService.getChildrenCascadeByClassifierIds(projectId,
                contextInstance, Stream.of(UMLDefinitionConstants.Class).collect(Collectors.toList()), true);
        final List<ModelPropertyInfo> classInfoList = modelPropertyInfoService.createModelPropertyInfoList(projectId,
                classInstanceList, Stream.of(UMLDefinitionConstants.Class_ownedAttribute,
                        UMLDefinitionConstants.Classifier_inheritedMember).collect(Collectors.toList()));
        final List<MetaClassInstance> propertyList = classInfoList.stream().flatMap(it -> {
            List<MetaClassInstance> properties = it.queryListInstanceValue(UMLDefinitionConstants.Class_ownedAttribute);
            properties.addAll(it.queryListInstanceValue(UMLDefinitionConstants.Classifier_inheritedMember));
            return properties.stream();
        }).collect(Collectors.toList());
        final Map<String, Set<String>> givenTypes = internalUmlService.getGivenTypes(projectId, propertyList);
        return propertyList.stream().filter(it -> givenTypes.containsKey(it.getId())).filter(it -> {
            Set<String> types = givenTypes.get(it.getId());
            return CollectionUtils.isNotEmpty(types) && types.contains(UMLDefinitionConstants.Property)
                    && !types.contains(UMLDefinitionConstants.Port);
        }).map(BasicRElement::getId).distinct().collect(Collectors.toList());
    }

    @NotNull
    public ModelResultVo updateAllocatedToByMode(UpdateAllocatedToByModeDTO dto) {
        LogUtil.printSerializeOnlineLogs("dto: ", dto);
        final String projectId = dto.getProjectId();
        final String allocationMode = dto.getAllocationMode();
        final List<MetaClassInstance> swimLines = internalUmlService.fetchInstanceByIds(dto.getInstanceIds(), projectId)
                .stream().filter(Objects::nonNull).collect(Collectors.toList());
        final List<ModelPropertyInfo> swimLineInfos = modelPropertyInfoService.createModelPropertyInfoList(projectId, swimLines,
                Stream.of(UMLDefinitionConstants.ActivityPartition_represents,
                        UMLDefinitionConstants.ActivityPartition_node).collect(Collectors.toList()));

        final List<MetaClassInstance> nodes = swimLineInfos.stream()
                .flatMap(it -> it.queryListInstanceValue(UMLDefinitionConstants.ActivityPartition_node).stream())
                .filter(Objects::nonNull).distinct().collect(Collectors.toList());
        final Map<String, ModelPropertyInfo> nodeInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId,
                nodes, Stream.of(UMLDefinitionConstants.CallBehaviorAction_behavior).collect(Collectors.toList()));

        LocalTransaction transaction = transactionService.createTransaction(projectId, UPDATE_MODEL);
        ModelResultVo modelResultVo = new ModelResultVo();
        try {
            swimLineInfos.stream().filter(swimLineInfo -> Objects.nonNull(swimLineInfo.queryInstanceValue(UMLDefinitionConstants.ActivityPartition_represents)))
                    .forEach(swimLineInfo -> {
                        MetaClassInstance represent = swimLineInfo.queryInstanceValue(UMLDefinitionConstants.ActivityPartition_represents);
                        List<ModelPropertyInfo> nodeInfos = swimLineInfo.queryListInstanceValue(UMLDefinitionConstants.ActivityPartition_node)
                                .stream().filter(it -> nodeInfoMap.containsKey(it.getId()))
                                .map(it -> nodeInfoMap.get(it.getId())).collect(Collectors.toList());
                        if (StringUtils.equals(AllocationModeEnum.DEFINITION.getValue(), allocationMode)) {
                            updateInPartitionByUsageMode.batchRemoveAllocateByUsageMode(projectId, nodeInfos, Stream.of(represent).collect(Collectors.toList()));
                            Optional.ofNullable(swimLineInfo).ifPresent(sli -> umlService.executeCreateModelDTO(updateActivityNodeInPartition.batchSetAllocateByDefinitionMode(
                                    projectId, nodeInfos, Stream.of(sli).collect(Collectors.toList()))));
                        } else if (StringUtils.equals(AllocationModeEnum.USAGE.getValue(), allocationMode)) {
                            updateActivityNodeInPartition.batchRemoveAllocateByDefinitionMode(projectId, nodeInfos, Stream.of(represent).collect(Collectors.toList()));
                            umlService.executeCreateModelDTO(updateInPartitionByUsageMode.batchSetAllocateByUsageMode(
                                    projectId, nodeInfos, Stream.of(swimLineInfo).collect(Collectors.toList())));
                        } else {
                            log.warn("分配模式类型异常，{}不是definition或usage", allocationMode);
                        }
                    });
            transactionService.commit(projectId);
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.UPDATE_MODEL_ERROR, e);
        }
        return modelResultVo;
    }

    public ModelResultVo deleteAllocateActivityPartition(DeleteAllocateActivityPartitionDTO deleteAllocateActivityPartitionDTO) {
        List<String> deleteInstances = new ArrayList<>();
        List<RemoveModelDto> removeModelDtos = new ArrayList<>();
        List<AppendModelDTO> appendModelDTOs = new ArrayList<>();

        String projectId = deleteAllocateActivityPartitionDTO.getProjectId();
        String allocationMode = deleteAllocateActivityPartitionDTO.getAllocationMode();

        List<DeletePartitionDTO> deletePartitionDTOS = new ArrayList<>();
        deletePartitionDTOS.addAll(deleteAllocateActivityPartitionDTO.getDeleteHorizontalPartitions());
        deletePartitionDTOS.addAll(deleteAllocateActivityPartitionDTO.getDeleteVerticalPartitions());

        List<String> instanceIds = new ArrayList<>();
        deletePartitionDTOS.forEach(temp -> {
            instanceIds.add(temp.getDeletePartitionId());
            instanceIds.addAll(temp.getActionIds());
            instanceIds.addAll(temp.getPartitionIds());
        });
        final Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(instanceIds, projectId);
        final List<MetaClassInstance> actionInstances = deletePartitionDTOS.stream().map(DeletePartitionDTO::getActionIds).flatMap(Collection::stream).
                filter(instanceMap::containsKey).map(instanceMap::get).collect(Collectors.toList());

        MofResultContainer inPartitionContainer = internalUmlService.getMofResultContainer(projectId, actionInstances, UMLDefinitionConstants.ActivityNode_inPartition);
        MofResultContainer representsContainer = internalUmlService.getMofResultContainer(projectId, new ArrayList<>(instanceMap.values()), UMLDefinitionConstants.ActivityPartition_represents);

        Map<String, List<MetaClassInstance>> partitionChildrenMap = new HashMap<>();
        Map<String, List<MetaClassInstance>> partitionMap = new HashMap<>();
        Map<String, DeletePartitionDTO> actionHorizontalMap = new HashMap<>();
        Map<String, DeletePartitionDTO> actionVerticalMap = new HashMap<>();

        deleteAllocateActivityPartitionDTO.getDeleteHorizontalPartitions().forEach(deletePartitionDTO -> {
            deletePartitionDTO.getActionIds().forEach(actionId -> actionHorizontalMap.put(actionId, deletePartitionDTO));
            deleteInstances.add(deletePartitionDTO.getDeletePartitionId());
        });
        deleteAllocateActivityPartitionDTO.getDeleteVerticalPartitions().forEach(deletePartitionDTO -> {
            deletePartitionDTO.getActionIds().forEach(actionId -> actionVerticalMap.put(actionId, deletePartitionDTO));
            deleteInstances.add(deletePartitionDTO.getDeletePartitionId());
        });

        LocalTransaction transaction = transactionService.createTransaction(projectId, DELETE_MODEL);
        ModelResultVo modelResultVo = new ModelResultVo();
        try {
            for (MetaClassInstance actionInstance : actionInstances) {
                // 动作所属分区
                List<MetaClassInstance> activityPartitions = inPartitionContainer.queryListInstanceProperty(actionInstance.getId(), UMLDefinitionConstants.ActivityNode_inPartition);

                // 判断动作 在交叉泳道 还是垂直或是水平泳道
                DeletePartitionDTO deleteHorizontalDTO = actionHorizontalMap.get(actionInstance.getId());
                DeletePartitionDTO deleteVerticalDTO = actionVerticalMap.get(actionInstance.getId());

                // 动作 同时删除水平和垂直泳道
                if (ObjectUtil.isNotEmpty(deleteHorizontalDTO) && ObjectUtil.isNotEmpty(deleteVerticalDTO)) {
                    List<MetaClassInstance> allInPartitionValues = new ArrayList<>();
                    allInPartitionValues.addAll(deleteHorizontalDTO.getPartitionIds().stream().filter(instanceMap::containsKey).map(instanceMap::get).collect(Collectors.toList()));
                    allInPartitionValues.addAll(deleteVerticalDTO.getPartitionIds().stream().filter(instanceMap::containsKey).map(instanceMap::get).collect(Collectors.toList()));

                    List<MetaClassInstance> deleteInPartitions = new ArrayList<>(activityPartitions);
                    deleteInPartitions.removeAll(allInPartitionValues);

                    List<MetaClassInstance> newInPartitions = new ArrayList<>(allInPartitionValues);
                    newInPartitions.removeAll(activityPartitions);

                    deletePartitionModel(projectId, actionInstance, representsContainer, allInPartitionValues, newInPartitions, deleteInPartitions, allocationMode);
                    if (ObjectUtil.isEmpty(allInPartitionValues)) {
                        deleteInstances.add(actionInstance.getId());
                    }

                    removeModelDtos.add(new RemoveModelDto(projectId, actionInstance.getId(), UMLDefinitionConstants.ActivityNode_inPartition, deleteInPartitions));
                    appendModelDTOs.add(new AppendModelDTO(projectId, actionInstance.getId(), UMLDefinitionConstants.ActivityNode_inPartition, new ArrayList<>(newInPartitions)));
                } else if (ObjectUtil.isNotEmpty(deleteHorizontalDTO) || ObjectUtil.isNotEmpty(deleteVerticalDTO)) {
                    DeletePartitionDTO deletePartitionDTO = deleteHorizontalDTO;
                    if (ObjectUtil.isNotEmpty(deleteVerticalDTO)) {
                        deletePartitionDTO = deleteVerticalDTO;
                    }

                    String deletePartitionId = deletePartitionDTO.getDeletePartitionId();
                    MetaClassInstance partitionInstance = instanceMap.get(deletePartitionId);
                    if (ObjectUtil.isEmpty(partitionInstance)) {
                        continue;
                    }

                    // 查询删除泳道 泳道父泳道和子泳道
                    if (ObjectUtil.isEmpty(partitionMap.get(deletePartitionId))) {
                        List<MetaClassInstance> childrenPartitions = internalUmlService.getChildrenCascade(projectId, partitionInstance, true).stream()
                                .filter(temp -> internalUmlService.checkInstanceType(projectId, temp, UMLDefinitionConstants.ActivityPartition)).collect(Collectors.toList());
                        Set<MetaClassInstance> parentPartitions = internalUmlService.getAncestor(projectId, partitionInstance).stream()
                                .filter(temp -> internalUmlService.checkInstanceType(projectId, temp, UMLDefinitionConstants.ActivityPartition)).collect(Collectors.toSet());
                        parentPartitions.addAll(childrenPartitions);
                        partitionChildrenMap.put(deletePartitionId, childrenPartitions);
                        partitionMap.put(deletePartitionId, new ArrayList<>(parentPartitions));
                    }

                    // 删除泳道对应 泳道链
                    List<String> partitionIds = Optional.ofNullable(partitionMap.get(deletePartitionId)).orElse(new ArrayList<>())
                            .stream().map(MetaClassInstance::getId).collect(Collectors.toList());

                    // 动作 所属水平分区
                    List<MetaClassInstance> verticalInPartitionValues = activityPartitions.stream().filter(temp -> !partitionIds.contains(temp.getId())).collect(Collectors.toList());
                    if (ObjectUtil.isEmpty(verticalInPartitionValues)) {
                        // 不是交叉泳道
                        deleteInstances.add(actionInstance.getId());
                    }
                    else {
                        List<MetaClassInstance> newInPartitions = deletePartitionDTO.getPartitionIds().stream().filter(instanceMap::containsKey).map(instanceMap::get).collect(Collectors.toList());
                        List<MetaClassInstance> allInPartitionValues = new ArrayList<>(verticalInPartitionValues);
                        allInPartitionValues.addAll(newInPartitions);

                        List<MetaClassInstance> deleteInPartitions = partitionChildrenMap.get(deletePartitionId);
                        // 动作 所属垂直分区
                        List<MetaClassInstance> horizontalInPartitionValues = activityPartitions.stream().filter(temp -> partitionIds.contains(temp.getId())).collect(Collectors.toList());
                        horizontalInPartitionValues.removeAll(deleteInPartitions);

                        newInPartitions.removeAll(horizontalInPartitionValues);

                        removeModelDtos.add(new RemoveModelDto(projectId, actionInstance.getId(), UMLDefinitionConstants.ActivityNode_inPartition, deleteInPartitions));
                        appendModelDTOs.add(new AppendModelDTO(projectId, actionInstance.getId(), UMLDefinitionConstants.ActivityNode_inPartition, new ArrayList<>(newInPartitions)));

                        deletePartitionModel(projectId, actionInstance, representsContainer, allInPartitionValues, newInPartitions, deleteInPartitions, allocationMode);
                    }
                } else {
                    deleteInstances.add(actionInstance.getId());
                }
            }

            umlService.removeModelByBatch(projectId, removeModelDtos);
            umlService.appendModelByBatch(projectId, appendModelDTOs);
            deleteService.deleteModels(projectId, deleteInstances);

            transactionService.commit(projectId);
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        }
        catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.DELETE_MODEL_ERROR, e);
        }
        return modelResultVo;
    }


    private void deletePartitionModel(String projectId, MetaClassInstance actionInstance, MofResultContainer representsContainer, List<MetaClassInstance> allNewInPartitionValues, List<MetaClassInstance> newInPartitions, List<MetaClassInstance> deleteInPartitions, String allocationMode) {
        final List<MetaClassInstance> representsList = allNewInPartitionValues.stream().map(inPartition ->
                representsContainer.queryInstanceProperty(inPartition.getId(), UMLDefinitionConstants.ActivityPartition_represents)).filter(Objects::nonNull).collect(Collectors.toList());

        updateActivityNodeInPartition.setInPartitionsByBatch(projectId, Stream.of(actionInstance).collect(Collectors.toList()), newInPartitions, allocationMode);
        updateActivityNodeInPartition.removeInPartitionsByBatch(projectId, Stream.of(actionInstance).collect(Collectors.toList()), deleteInPartitions, representsList, allocationMode);
    }
}
